//
//  ImageCropperView.m
//  HiMaster3
//
//  Created by jinghao on 16/5/5.
//  Copyright © 2016年 jinghao. All rights reserved.
//

#import "ImageCropperView.h"
#import <QuartzCore/QuartzCore.h>
#include <math.h>

typedef NS_ENUM(NSUInteger, ActionViewTag) {
    
    OriginViewTag = 111,
    
    CropViewTag
};

static CGPoint PreviousTapPoint = (CGPoint){0,0};
//记录图片最小的缩放大小
static  CGSize originImageViewSmallSize = (CGSize){0,0};
//记录图片最大的缩放大小
static  CGSize originImageViewBigestSize = (CGSize){0,0};

static CGAffineTransform PreviousAffineTransform = (CGAffineTransform){1,0,0,1,0,0};


static const CGSize kCropViewDefaultSize = (CGSize){200,200};



@interface ImageCropperView()<UINavigationControllerDelegate,UIImagePickerControllerDelegate,UIGestureRecognizerDelegate,UIScrollViewDelegate>
{
    UIView * horizontalLine0;
    UIView * horizontalLine1;
    UIView * verticalLine0;
    UIView * verticalLine1;
    UIPinchGestureRecognizer *pinchOriginGestureRecognizer;
    UIPanGestureRecognizer *panOriginGestureRecognizer;
    UIRotationGestureRecognizer *rotationOriginGestureRecognizer;
}
@property (strong, nonatomic) UIView *cropView;//裁剪
@property (strong, nonatomic) UIView *originImageBoardView;
@property (nonatomic, strong,readwrite) UIImageView *imageView;//图片
@property (nonatomic, strong,readwrite) UIImageView *addImageView;//添加图片
@property(nonatomic,strong)UIView * shadeView;//蒙版
@property(nonatomic,assign)CGPoint imageOriginCenter;//原始图片中心点

@property (nonatomic,strong)UIScrollView *superScrollView;

@end

@implementation ImageCropperView

- (void)initViews{
    
    //原始图片底板
    self.originImageBoardView = [[UIView alloc] init];
    self.originImageBoardView.tag = OriginViewTag;
    self.originImageBoardView.clipsToBounds = YES;
    self.clipsToBounds = YES;
    [self addSubview:self.originImageBoardView];
    [self.originImageBoardView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self);
    }];
    
    
    //原始图片初始化
    self.imageView = [[UIImageView alloc] init];
    [self.originImageBoardView addSubview:self.imageView];
    
    
    self.addImageView = [[UIImageView alloc] init];
    self.addImageView.image = [UIImage imageNamed:@"add_icon"];
    [self addSubview:self.addImageView];
    
    //裁剪图片view
    self.cropView = [[UIView alloc] init];
    self.cropView.tag = CropViewTag;
    [self.originImageBoardView  addSubview:self.cropView];

    [self.cropView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self.originImageBoardView);
    }];
    
    self.shadeView = [[UIView alloc] initWithFrame:self.originImageBoardView.bounds];
    self.shadeView.alpha = 0.5;
    [self.originImageBoardView  addSubview:self.shadeView];
    [self.shadeView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.originImageBoardView);
    }];
    
    [self.addImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.mas_equalTo(self.mas_centerX);
        make.centerY.mas_equalTo(self.mas_centerY);
        make.height.mas_equalTo(@(70));
        make.width.mas_equalTo(@(70));
    }];
    @weakify(self);
    [self.addImageView setTapActionWithBlock:^(UIGestureRecognizer *gestureRecoginzer) {
        @strongify(self);
        [self addImageButtonOnClick:nil];
    }];
    
    
    [self.originImageBoardView setTapActionWithBlock:^(UIGestureRecognizer *gestureRecoginzer) {
        @strongify(self);
        [self showMenuController];
    }];
    
    horizontalLine0 = [[UIView alloc] init];
    horizontalLine0.backgroundColor = [UIColor whiteColor];
    [self addSubview:horizontalLine0];
    
    [horizontalLine0 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.and.right.equalTo(self);
        make.height.mas_equalTo(1.0f);
        make.centerY.equalTo(self).with.offset(-50.0f);
    }];
    
    horizontalLine1 = [[UIView alloc] init];
    horizontalLine1.backgroundColor = [UIColor whiteColor];
    [self addSubview:horizontalLine1];
    [horizontalLine1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.and.right.equalTo(self);
        make.height.mas_equalTo(1.0f);
        make.centerY.equalTo(self).with.offset(50.0f);
    }];
    
    verticalLine0 = [[UIView alloc] init];
    verticalLine0.backgroundColor = [UIColor whiteColor];
    [self addSubview:verticalLine0];
    [verticalLine0 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.and.bottom.equalTo(self);
        make.width.mas_equalTo(1.0f);
        make.centerX.equalTo(self).with.offset(-50.0f);
    }];
    
    verticalLine1 = [[UIView alloc] init];
    verticalLine1.backgroundColor = [UIColor whiteColor];
    [self addSubview:verticalLine1];
    [verticalLine1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.and.bottom.equalTo(self);
        make.width.mas_equalTo(1.0f);
        make.centerX.equalTo(self).with.offset(50.0f);
    }];
    
    [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self.originImageBoardView);
    }];
    
    self.cropView.backgroundColor = [UIColor redColor];
    self.cropView.hidden = YES;
//    self.originImageBoardView.backgroundColor = [UIColor blueColor];
//    self.shadeView.backgroundColor = [UIColor greenColor];
    
    self.enable = NO;
}


- (UIScrollView*)superScrollView{
    if (!_superScrollView) {
        UIView *superView = [self superview];
        while (superView && ![superView isKindOfClass:[UIScrollView class]]) {
            superView = [superView superview];
        }
        if ([superView isKindOfClass:[UIScrollView class]]) {
            _superScrollView = (UIScrollView*)superView;
        }
    }
    return _superScrollView;
}

- (void)setSuperScrollViewEnabled:(BOOL)scrollEnabled
{
    if (self.enable) {
        self.superScrollView.scrollEnabled = scrollEnabled;
    }
}

- (void)checkUIGestureRecognizer:(UIGestureRecognizer*)sender
{
    if ([sender state] == UIGestureRecognizerStateEnded) {
        [self setSuperScrollViewEnabled:YES];
    }
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self setSuperScrollViewEnabled:NO];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self setSuperScrollViewEnabled:YES];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self initViews];
    }
    return self;
}

- (id)init
{
    return [self initWithFrame:CGRectZero];
}

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    
    if (self) {
        self.frame = frame;
        [self initViews];
    }
    
    return self;
}

- (void)setEnable:(BOOL)enable
{
    if (enable==_enable) {
        return;
    }
    _enable = enable;
    verticalLine0.hidden = !enable;
    verticalLine1.hidden = !enable;
    horizontalLine0.hidden = !enable;
    horizontalLine1.hidden = !enable;
    if (enable) {
        [self bindGestureAction];
    }else{
        [self unbindGestureAction];

    }
}

- (void)bindGestureAction {
    pinchOriginGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGestureAction:)];
    panOriginGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureAction:)];
    panOriginGestureRecognizer.maximumNumberOfTouches = 1;
    rotationOriginGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotationGestureAction:)];
    pinchOriginGestureRecognizer.delegate = panOriginGestureRecognizer.delegate = rotationOriginGestureRecognizer.delegate = self;
    [self.originImageBoardView addGestureRecognizer:pinchOriginGestureRecognizer];
    [self.originImageBoardView addGestureRecognizer:panOriginGestureRecognizer];
    panOriginGestureRecognizer.maximumNumberOfTouches = 1;
}

- (void)unbindGestureAction{
    [self.originImageBoardView removeGestureRecognizer:pinchOriginGestureRecognizer];
    [self.originImageBoardView removeGestureRecognizer:panOriginGestureRecognizer];
}

- (void)longPressImage:(id)sender{
    [self checkUIGestureRecognizer:sender];
    [self showMenuController];
}

- (UIImage*)croppedImage
{
    if (_croppedImage==nil) {
        [self finishCropping];
    }
    return _croppedImage;
}

- (void)setImage:(UIImage *)image
{
    self.cropSize = self.bounds.size;
    
    if (_image != image) {
        _image = image;
    }
//    [self.imageView setImage:image];
    if (image) {
        self.addImageView.hidden = YES;
        [self reset];
    }else{
        self.addImageView.hidden = NO;
    }
}

- (void)finishCropping {
    self.shadeView.hidden = YES;
//    UIGraphicsBeginImageContext(self.originImageBoardView.bounds.size); //currentView 当前的view
    
    CGSize size = CGSizeMake(self.originImageBoardView.bounds.size.width * [UIScreen mainScreen].scale, self.originImageBoardView.bounds.size.height * [UIScreen mainScreen].scale);
    UIGraphicsBeginImageContextWithOptions(size,NO,[UIScreen mainScreen].scale);
    [self.originImageBoardView.layer renderInContext:UIGraphicsGetCurrentContext()];
    
    UIImage *originFullImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    CGImageRef imageRef = originFullImage.CGImage;
    CGRect frame = self.cropView.frame;
    frame.size = size;
    frame.origin.x = 0;
    frame.origin.y =0 ;
    CGImageRef imagePartRef = CGImageCreateWithImageInRect(imageRef, frame);

//    CGImageRef imagePartRef = CGImageCreateWithImageInRect(imageRef, self.cropView.frame);
    _croppedImage = [UIImage imageWithCGImage:imagePartRef];
    CGImageRelease(imagePartRef);
#ifdef DEBUG
    UIImageWriteToSavedPhotosAlbum(_croppedImage, self, nil, nil);
#endif
}

- (void)reset
{
    if(CGSizeEqualToSize(self.cropSize,CGSizeZero))
    {
        self.cropSize = kCropViewDefaultSize;
    }
    if (self.image.size.width <= self.cropSize.width || self.image.size.height <= self.cropSize.height) {
        self.imageView.frame = CGRectMake(0, 0,self.cropSize.width, self.cropSize.height);
    }
    
    if (self.image.size.width > self.image.size.height) {
        self.imageView.frame = CGRectMake(0, 0,self.cropSize.height *  self.image.size.width / self.image.size.height, self.cropSize.height);
        
    }else{
        self.imageView.frame = CGRectMake(0, 0,self.cropSize.width,self.cropSize.width * self.image.size.height / self.image.size.width);
    }
    
    
    originImageViewSmallSize = CGSizeMake(self.imageView.frame.size.width, self.imageView.frame.size.height);
    
    originImageViewBigestSize = CGSizeMake(self.image.size.width * 2, self.image.size.height * 2);
    
    
    self.imageView.image = self.image;
//    self.imageView.center = self.originImageBoardView.center;
    
//    self.cropView.center = self.originImageBoardView.center;
//    
//    self.cropView.bounds = CGRectMake(0, 0, self.cropSize.width, self.cropSize.height);
//    
    
//    self.shadeView.center = self.originImageBoardView.center;
    
}


- (void)addImageButtonOnClick:(id)sender{
    [self.superViewController showActionSheetForImage:self allowsEditing:self.allowsEditing];
}

- (void)setImageScale:(float)imageScale
{
    if (_imageScale!=imageScale) {
        _imageScale = imageScale;
    }
}

- (void)setCropSize:(CGSize)cropSize
{
    _cropSize = cropSize;
    [self.cropView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.mas_equalTo(cropSize.height);
        make.width.mas_equalTo(cropSize.width);
    }];
}

#pragma mark gesture recognizer action

- (void)pinchGestureAction:(UIPinchGestureRecognizer *)gestureRecognizer {
    
    [self checkUIGestureRecognizer:gestureRecognizer];
    
    UIView *gestureView = gestureRecognizer.view;
    
    if(gestureView.tag == OriginViewTag) {
        gestureView = self.imageView;
    }
    CGAffineTransform affineTransform = CGAffineTransformScale(gestureView.transform,gestureRecognizer.scale, gestureRecognizer.scale);
    
    gestureView.transform = affineTransform;
    
    gestureRecognizer.scale = 1;
    
    if(gestureRecognizer.view.tag == OriginViewTag) {
        
        
        NSLog(@"放大缩放之后的图片坐标:%@",NSStringFromCGRect(self.imageView.frame));
        
        if (self.imageView.frame.size.width <= originImageViewSmallSize.width || self.imageView.frame.size.height <= originImageViewSmallSize.height){
            
            self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y,originImageViewSmallSize.width, originImageViewSmallSize.height);
            
        }
        
        if (self.imageView.frame.size.width >= originImageViewBigestSize.width || self.imageView.frame.size.height >= originImageViewBigestSize.height) {
            
            self.imageView.frame = CGRectMake(self.imageView.frame.origin.x, self.imageView.frame.origin.y,originImageViewBigestSize.width, originImageViewBigestSize.height);
        }
        
        
        
        if (self.imageView.frame.origin.x >= self.cropView.frame.origin.x ) {
            
            
            self.imageView.frame = CGRectMake(self.cropView.frame.origin.x, self.imageView.frame.origin.y, self.imageView.frame.size.width, self.imageView.frame.size.height);
            
        }
        
        
        if (self.cropView.frame.origin.x + self.cropView.width - self.imageView.frame.size.width >= self.imageView.frame.origin.x) {
            
            
            self.imageView.frame = CGRectMake(self.cropView.frame.origin.x + self.cropView.width - self.imageView.frame.size.width, self.imageView.frame.origin.y, self.imageView.frame.size.width, self.imageView.frame.size.height);
        }
        
        if (self.imageView.frame.origin.y >= self.cropView.frame.origin.y){
            
            self.imageView.frame = CGRectMake(self.imageView.frame.origin.x,self.cropView.frame.origin.y,self.imageView.frame.size.width, self.imageView.frame.size.height);
            
        }
        
        if (self.cropView.frame.origin.y + self.cropView.height - self.imageView.frame.size.height >= self.imageView.frame.origin.y) {
            self.imageView.frame = CGRectMake(self.imageView.frame.origin.x,self.cropView.frame.origin.y + self.cropView.height - self.imageView.frame.size.height , self.imageView.frame.size.width, self.imageView.frame.size.height);
        }
        return;
    }
    
    if(!CGRectContainsRect(self.originImageBoardView.frame, gestureView.frame)) {
        
        gestureView.transform = PreviousAffineTransform;
        
        return;
    }
    
    PreviousAffineTransform = gestureView.transform;
    
    
}

- (void)panGestureAction:(UIPanGestureRecognizer *)gestureRecognizer {

    [self checkUIGestureRecognizer:gestureRecognizer];

    UIView *gestureView = gestureRecognizer.view,
    
    *gestureViewSuperView = gestureView.superview;
    
    BOOL needPaddingDistance = NO;
    
    if(gestureView.tag == OriginViewTag) {
        
        gestureView = self.imageView;
        
        needPaddingDistance = NO;
        
    }
    else if (gestureView.tag == CropViewTag) {
        
        needPaddingDistance = YES;
        
        gestureViewSuperView = self.originImageBoardView;
        
    }
    
    CGPoint touchPoint = [gestureRecognizer locationInView:gestureView.superview];
    
    if(gestureRecognizer.state == UIGestureRecognizerStateChanged) {
        
        CGPoint centerPoint = CGPointMake(gestureView.center.x + touchPoint.x - PreviousTapPoint.x, gestureView.center.y + touchPoint.y - PreviousTapPoint.y);
        
        
        if(needPaddingDistance) {
            CGFloat w = CGRectGetWidth(gestureView.frame),
            h = CGRectGetHeight(gestureView.frame);
            CGRect tempFrame = CGRectMake(centerPoint.x - w / 2, centerPoint.y - h / 2, w, h);
            if(!CGRectContainsRect(gestureViewSuperView.frame, tempFrame)) {
                return;
            }
        }
        
        gestureView.center = centerPoint;
        
        
        
        if (self.imageView.frame.origin.x >= self.cropView.frame.origin.x  ) {
            
            
            self.imageView.frame = CGRectMake(self.cropView.frame.origin.x, self.imageView.frame.origin.y, self.imageView.frame.size.width, self.imageView.frame.size.height);
            
        }
        
        
        if (self.cropView.frame.origin.x + self.cropView.width - self.imageView.frame.size.width >= self.imageView.frame.origin.x) {
            
            
            self.imageView.frame = CGRectMake(self.cropView.frame.origin.x + self.cropView.width - self.imageView.frame.size.width, self.imageView.frame.origin.y, self.imageView.frame.size.width, self.imageView.frame.size.height);
        }
        
        if (self.imageView.frame.origin.y >= self.cropView.frame.origin.y){
            
            self.imageView.frame = CGRectMake(self.imageView.frame.origin.x,self.cropView.frame.origin.y,self.imageView.frame.size.width, self.imageView.frame.size.height);
            
        }
        
        if (self.cropView.frame.origin.y + self.cropView.height - self.imageView.frame.size.height >= self.imageView.frame.origin.y) {
            
            
            self.imageView.frame = CGRectMake(self.imageView.frame.origin.x,self.cropView.frame.origin.y + self.cropView.height - self.imageView.frame.size.height , self.imageView.frame.size.width, self.imageView.frame.size.height);
            
        }
        
        
        
    }
    
    
    PreviousTapPoint = touchPoint;
    
    [gestureRecognizer setTranslation:CGPointZero inView:gestureView.superview];
}

- (void)rotationGestureAction:(UIRotationGestureRecognizer *)gestureRecognizer {
    [self checkUIGestureRecognizer:gestureRecognizer];

    UIView *gestureView = gestureRecognizer.view;
    if(gestureView.tag == OriginViewTag) {
        gestureView = self.imageView;
    }
    if(gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        PreviousTapPoint = gestureView.center;
    }
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan || gestureRecognizer.state == UIGestureRecognizerStateChanged) {
        gestureView.transform = CGAffineTransformRotate(gestureView.transform, gestureRecognizer.rotation);
        gestureView.center = PreviousTapPoint;
        [gestureRecognizer setRotation:0];
    }
}

- (UIImage *)generateCropImage {
    
    self.shadeView.hidden = YES;
    
    UIGraphicsBeginImageContext(self.originImageBoardView.bounds.size); //currentView 当前的view
    [self.originImageBoardView.layer renderInContext:UIGraphicsGetCurrentContext()];
    
    UIImage *originFullImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    CGImageRef imageRef = originFullImage.CGImage;
    CGImageRef imagePartRef = CGImageCreateWithImageInRect(imageRef, self.cropView.frame);
    UIImage *cropImage = [UIImage imageWithCGImage:imagePartRef];
    CGImageRelease(imagePartRef);
    
    return cropImage;
}



#pragma mark --  UIGestureRecognizerDelegate
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}


#pragma mark --

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
    self.image = image;
    NSMutableDictionary * dict= [NSMutableDictionary dictionaryWithDictionary:editingInfo];
    
    [dict setObject:image forKey:@"UIImagePickerControllerEditedImage"];
    [picker dismissViewControllerAnimated:YES completion:nil];
    //直接调用3.x的处理函数
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [picker dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark -- 

- (void)showMenuController{
    [self becomeFirstResponder];
    UIMenuItem *editMenuItem = [[UIMenuItem alloc] initWithTitle:self.enable?@"完成":@"编辑"
                                                      action:@selector(editMenuItemOnClick:)];
    UIMenuItem *changeImageMenuItem = [[UIMenuItem alloc] initWithTitle:@"更换照片"
                                                          action:@selector(changeImageMenuItemOnClick:)];
    UIMenuItem *resetMenuItem = [[UIMenuItem alloc] initWithTitle:@"重置"
                                                          action:@selector(resetMenuItemOnClick:)];
    if(self.enable){
        [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:editMenuItem, changeImageMenuItem,resetMenuItem,nil]];
    }else{
        [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:editMenuItem,nil]];
    }
    [[UIMenuController sharedMenuController] setTargetRect:self.frame inView:self.superview.superview];
    [[UIMenuController sharedMenuController] setMenuVisible:YES animated: YES];
}

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    
    return [super canPerformAction:action withSender:sender];
}

- (void)editMenuItemOnClick:(id)sender{
    if (self.enable) {
        [self finishCropping];
        [self setSuperScrollViewEnabled:YES];
    }
    self.enable = !self.enable;
}

- (void)changeImageMenuItemOnClick:(id)sender{
    [self addImageButtonOnClick:nil];
}

- (void)resetMenuItemOnClick:(id)sender{
    [self reset];
}

@end